%% Copyright (C) 2007 Vijay Gajula <gajulak@gmail.com>.
%% All rights reserved.
%%
%% Redistribution and use in source and binary forms, with or without
%% modification, are permitted provided that the following conditions
%% are met:
%%
%% 1. Redistributions of source code must retain the above copyright
%%    notice, this list of conditions and the following disclaimer.
%% 2. Redistributions in binary form must reproduce the above
%%    copyright notice, this list of conditions and the following
%%    disclaimer in the documentation and/or other materials provided
%%    with the distribution.
%%
%% THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
%% OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
%% WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
%% ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
%% DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
%% DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
%% GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
%% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
%% WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
%% NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
%% SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

-module(mod_ipsecvpn).
-vsn(1.0).
-author('gajulak@gmail.com').
-export([process_get/1, process_edit/1, sys_ipsecvpn/1]).
-export([ipsecvpn_info/1]).

-include("xmerl.hrl").
-include("netconf.hrl").

-define(TREE, { name,
		[ local_id_type,   	 %% ip, fqdn, ufqdn, dn
		  local_id,  
		  remote_ip,
		  remote_id_type,   	 %% ip, fqdn, ufqdn, dn
		  remote_id,
		  auth_type,   		 %% preshared, certificate
		  mode,		 	 %% main, aggressive
		  auth_alg,    	 	 %% md5, sha1, sha2
		  enc_alg,     	 	 %% 3des, aes128, aes192, aes256
		  secret,      		 %% incase of preshared key
		  certificate, 		 %% incase of certifcate
		  keylife,     		 %% in hrs, 2days
		  dh_group,	 	 %% group1, group2, group5
		  ipsec_protocol,  	 %% ah,esp
		  ipsec_auth_alg,  	 %% md5, sha1, sha2
		  ipsec_enc_alg,  	 %% 3des, aes128, aes192, aes256
		  ipsec_keylife,    	 %% in hrs, 1 day
		  ipsec_lifebytes,    	 %% in GBs, 0 - unlimted 
		  pfs,
		  dpd,     		 %% yes or no
		  nat_traversal,
		  status
		 ]}).



process_get(E) ->
	%% io:format("mod_ipsecvpn:~p~n",[E]),
	sys_ipsecvpn(E).

sys_ipsecvpn([#xmlElement{name = all}=E|T]) 
   when record(E, xmlElement) ->
	ipsecvpn_info(all);
	
sys_ipsecvpn([H|T]) -> sys_ipsecvpn(T);
sys_ipsecvpn([]) -> ok.

ipsecvpn_info(all) ->
	IpsecVpn = db:get_ipsecvpn(),
	Xml = generate_xml(IpsecVpn, []),
	{ok, Xml}.

generate_xml([], Xml) -> Xml;
generate_xml([H|T], Xml) ->
     Str = io_lib:format("
			<ipsecvpn>
			<name>~s</name>
			<local_id_type>~p</local_id_type>
			<local_id>~s</local_id>
			<remote_ip>~s</remote_ip>
			<remote_id_type>~p</remote_id_type>
			<remote_id>~p</remote_id>
			<auth_type>~p</auth_type>
			<mode>~p</mode>
			<auth_alg>~p</auth_alg>
			<enc_alg>~p</enc_alg>
			<secret>~s</secret>
			<certificate>~p</certificate>
			<keylife>~p</keylife>
			<dh_group>~p</dh_group>
			<ipsec_protocol>~p</ipsec_protocol>
			<ipsec_auth_alg>~p</ipsec_auth_alg>
			<ipsec_enc_alg>~p</ipsec_enc_alg>
			<ipsec_keylife>~p</ipsec_keylife>
			<ipsec_lifbytes>~p</ipsec_lifbytes>
			<pfs>~p</pfs>
			<dpd>~p</dpd>
			<nat_traversal>~p</nat_traversal>
			<status>~p</status>
			</ipsecvpn>~n", 
			[H#ipsecvpn.name, 
			 H#ipsecvpn.local_id_type, 
			 H#ipsecvpn.local_id,
		  	 H#ipsecvpn.remote_ip,
		  	 H#ipsecvpn.remote_id_type,
		  	 H#ipsecvpn.remote_id,
		  	 H#ipsecvpn.auth_type,   
		  	 H#ipsecvpn.mode,	
		  	 H#ipsecvpn.auth_alg, 
		  	 H#ipsecvpn.enc_alg, 
		  	 H#ipsecvpn.secret, 
		  	 H#ipsecvpn.certificate,
		  	 H#ipsecvpn.keylife,   
		  	 H#ipsecvpn.dh_group,
		  	 H#ipsecvpn.ipsec_protocol,
		  	 H#ipsecvpn.ipsec_auth_alg,
		  	 H#ipsecvpn.ipsec_enc_alg,
		  	 H#ipsecvpn.ipsec_keylife,
		  	 H#ipsecvpn.ipsec_lifebytes,
		  	 H#ipsecvpn.pfs,
		  	 H#ipsecvpn.dpd,     	
		  	 H#ipsecvpn.nat_traversal,
		  	 H#ipsecvpn.status]),
      generate_xml(T, Xml++Str).


process_edit(E) ->
	%% io:format("mod_ipsecvpn:~p~n",[E]),
	R = top_node(?TREE, E, #ipsecvpn{}),
	%% io:format("End process_edit:~p~n",[R]),
	R.

top_node({Node, SubNode}, [#xmlElement{name = Node}=E|T], If) 
   when record(E, xmlElement) ->
	%% io:format("11 ~p~n",[E]),
	Val = get_text(E#xmlElement.content),
	%% io:format("Name:~p~n",[Val]),
	case db:get_ipsecvpn(Val) of 
	     [] -> 	
	     		Str = io_lib:format("<error/>",[]),
	             	{ok, Str};
		[If1] ->  %% io:format("DB If : ~p~n", [If1]), 
			sub_node(SubNode, T, If1)
	end;

top_node(Tree, [H|T], If) when record(H, xmlElement) ->
	%% io:format("22, E~p~n",[H]),
	top_node(Tree, T, If);

top_node(Tree, [H|T], If) when record(H, xmlText) ->
	%% io:format("331  ~p~n",[H]),
	top_node(Tree, T, If);

top_node(_, [], If) ->
	%% io:format("INTERFACE SET11:~p~n", [If]),
	Str = io_lib:format("<ok/>",[]),
	{ok, Str};

top_node(Node, _E, _If) ->
	io:format("Error:~p~n",[_E]),
	Str = io_lib:format("<error/>",[]),
	{ok, Str}.

sub_node(SNodes, [E|T], If) ->
	%% io:format("4444  ~p~n",[E]),
	If2 = process_attributes(SNodes, E, If),
	%% io:format("55  ~p~n",[T]),
	sub_node(SNodes, T, If2);

sub_node(_, [], If) ->
	%% io:format("INTERFACE SET22:~p~n", [If]),
	db:set_record(If),
	Str = io_lib:format("<ok/>",[]),
	{ok, Str}.

process_attribute(local_id_type, #xmlElement{name = local_id_type}=E, If) 
   when record(E, xmlElement) ->
	Val = get_text(E#xmlElement.content),
	{true, If#ipsecvpn{ local_id_type = Val }};

process_attribute(local_id, #xmlElement{name = local_id}=E, If) 
   when record(E, xmlElement) ->
	Val = get_text(E#xmlElement.content),
	{true, If#ipsecvpn{ local_id = Val }};

process_attribute(remote_ip, #xmlElement{name = remote_ip}=E, If) 
   when record(E, xmlElement) ->
	Val = get_text(E#xmlElement.content),
	{true, If#ipsecvpn{ remote_ip = Val }};

process_attribute(remote_id_type, #xmlElement{name = remote_id_type}=E, If) 
   when record(E, xmlElement) ->
	Val = get_text(E#xmlElement.content),
	{true, If#ipsecvpn{ remote_id_type = Val }};

process_attribute(remote_id, #xmlElement{name = remote_id}=E, If) 
   when record(E, xmlElement) ->
	Val = get_text(E#xmlElement.content),
	{true, If#ipsecvpn{ remote_id = Val }};

process_attribute(auth_type, #xmlElement{name = auth_type}=E, If) 
   when record(E, xmlElement) ->
	Val = get_text(E#xmlElement.content),
	{true, If#ipsecvpn{ auth_type = Val }};

process_attribute(mode, #xmlElement{name = mode}=E, If) 
   when record(E, xmlElement) ->
	Val = get_text(E#xmlElement.content),
	{true, If#ipsecvpn{ mode = Val }};

process_attribute(auth_alg, #xmlElement{name = auth_alg}=E, If) 
   when record(E, xmlElement) ->
	Val = get_text(E#xmlElement.content),
	{true, If#ipsecvpn{ auth_alg = Val }};

process_attribute(enc_alg, #xmlElement{name = enc_alg}=E, If) 
   when record(E, xmlElement) ->
	Val = get_text(E#xmlElement.content),
	{true, If#ipsecvpn{ enc_alg = Val }};

process_attribute(secret, #xmlElement{name = secret}=E, If) 
   when record(E, xmlElement) ->
	Val = get_text(E#xmlElement.content),
	{true, If#ipsecvpn{ secret = Val }};

process_attribute(certificate, #xmlElement{name = certificate}=E, If) 
   when record(E, xmlElement) ->
	Val = get_text(E#xmlElement.content),
	{true, If#ipsecvpn{ certificate = Val }};

process_attribute(keylife, #xmlElement{name = keylife}=E, If) 
   when record(E, xmlElement) ->
	Val = get_text(E#xmlElement.content),
	{true, If#ipsecvpn{ keylife = Val }};

process_attribute(dh_group, #xmlElement{name = dh_group}=E, If) 
   when record(E, xmlElement) ->
	Val = get_text(E#xmlElement.content),
	{true, If#ipsecvpn{ dh_group = Val }};

process_attribute(ipsec_protocol, #xmlElement{name = ipsec_protocol}=E, If) 
   when record(E, xmlElement) ->
	Val = get_text(E#xmlElement.content),
	{true, If#ipsecvpn{ ipsec_protocol = Val }};

process_attribute(ipsec_auth_alg, #xmlElement{name = ipsec_auth_alg}=E, If) 
   when record(E, xmlElement) ->
	Val = get_text(E#xmlElement.content),
	{true, If#ipsecvpn{ ipsec_auth_alg = Val }};

process_attribute(ipsec_enc_alg, #xmlElement{name = ipsec_enc_alg}=E, If) 
   when record(E, xmlElement) ->
	Val = get_text(E#xmlElement.content),
	{true, If#ipsecvpn{ ipsec_enc_alg = Val }};

process_attribute(ipsec_keylife, #xmlElement{name = ipsec_keylife}=E, If) 
   when record(E, xmlElement) ->
	Val = get_text(E#xmlElement.content),
	{true, If#ipsecvpn{ ipsec_keylife = Val }};

process_attribute(ipsec_lifebytes, #xmlElement{name = ipsec_lifebytes}=E, If) 
   when record(E, xmlElement) ->
	Val = get_text(E#xmlElement.content),
	{true, If#ipsecvpn{ ipsec_lifebytes = Val }};

process_attribute(pfs, #xmlElement{name = pfs}=E, If) 
   when record(E, xmlElement) ->
	Val = get_text(E#xmlElement.content),
	{true, If#ipsecvpn{ pfs = Val }};

process_attribute(dpd, #xmlElement{name = dpd}=E, If) 
   when record(E, xmlElement) ->
	Val = get_text(E#xmlElement.content),
	{true, If#ipsecvpn{ dpd = Val }};

process_attribute(nat_traversal, #xmlElement{name = nat_traversal}=E, If) 
   when record(E, xmlElement) ->
	Val = get_text(E#xmlElement.content),
	{true, If#ipsecvpn{ nat_traversal = Val }};

process_attribute(status, #xmlElement{name = status}=E, If) 
   when record(E, xmlElement) ->
	Val = get_text(E#xmlElement.content),
	{true, If#ipsecvpn{ status = Val }};

process_attribute(_, _, If) -> 
	%% io:format("122  ~p~n",[If]),
	{false, If}.
	
process_attributes([H|T], E, If) when record(E, xmlElement) ->
	case process_attribute(H, E, If) of
	   {true, If1} -> If1;
	   {false, _If2} -> process_attributes(T, E, If)
	end;
process_attributes(_, _, If) ->
	%% io:format("133  ~p~n",[If]),
	If.

get_text([X|_]) when record(X, xmlText) ->  X#xmlText.value;
get_text(_) ->  [].
